home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
net3d-0.08
/
server.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-22
|
7KB
|
277 lines
/* server.c
*
* Contains code needed to start and run the game server.
*/
#include "net3d.h"
#include <netdb.h>
#include <netinet/in.h>
static void displayhelp(char *);
int main(int argc, char **argv)
{
int mainsock; /* socket used for accepting new players */
int psocks[MAX_PLAYERS]; /* sockets connecting to players */
fd_set fds; /* file descriptors for select */
int plcount=0; /* number of players */
char *pnames[MAX_PLAYERS]; /* names of players */
struct object *ohead=NULL; /* object list */
struct vehicle *vhead=NULL; /* vehicle list */
struct map mp={NULL, NULL, 0, 0, 0.0, 0.0, {0,0,300}};
/* game world terrain details */
struct vehicle *vpos; /* vehicle assigned to each player */
struct vehicle *pvehicles[MAX_PLAYERS];
/* vehicles owned by players */
int finalcountdown=100; /* frames between death of the last
* player and the end of the game */
char *filepaths[50]; /* actual paths to .v files given on
* command line */
int i; /* scratch variables */
int j;
if (argc == 1) {
printf("usage : Server mode : %s <vehicle files>\n",argv[0]);
printf(" Help : %s -help\n",argv[0]);
exit(0);
}
if (!strcmp(argv[1],"-help")) {
displayhelp(argv[0]);
exit(0);
}
/* We want children reaped automatically by default. */
signal(SIGCHLD, SIG_IGN);
initcaches();
readextravehicles(); /* read extra vehicles from internal array */
/* For each vehicle file on the command line, pass it through cpp
* before reading into the object and vehicle lists.
*/
for(i=1; i<argc; i++) {
int pifd; /* file descriptor for pipe */
struct stat dummy;
char currentdir[100]; /* path to .v file in current dir */
char net3ddir[100]; /* path to .v file in NET3D_DIR */
/* Look for the file in the current directory and in NET3D_DIR,
* then pipe it through cpp.
*/
sprintf(currentdir,"%s",argv[i]);
sprintf(net3ddir,"%s/%s",NET3D_DIR,argv[i]);
if (stat(currentdir,&dummy) != -1) {
pifd=pipethrough(CPPPATH,currentdir);
readfile(&ohead,&vhead,pifd,&mp);
printf("done reading %s\n",currentdir);
close(pifd);
filepaths[i] = strdupe(currentdir);
}
else if (stat(net3ddir,&dummy) != -1) {
pifd=pipethrough(CPPPATH,net3ddir);
readfile(&ohead,&vhead,pifd,&mp);
printf("done reading %s\n",net3ddir);
close(pifd);
filepaths[i] = strdupe(net3ddir);
}
else {
printf("file %s not found\n",argv[i]);
exit(0);
}
}
/* check if a sensible world was read in */
if (vhead==NULL) {
printf("No vehicles available for use\n");
exit(1);
}
else {
makemap(&ohead,&mp);
worldinfo(vhead,ohead);
printf("Waiting for players... hit return to start game\n");
}
/* open initial socket for connections from clients */
mainsock=OpenDest();
do {
/* wait for either a key-press or a new connection */
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(mainsock,&fds);
#ifdef __hpux
select(mainsock+1,(int *)&fds,NULL,NULL,NULL);
#else
select(mainsock+1,&fds,NULL,NULL,NULL);
#endif
if (FD_ISSET(mainsock,&fds)) {
char *hname;
/* A new connection has arrived.
*/
struct sockaddr_in newaddr;
struct hostent *newhost;
int newaddrsize;
/* accept incoming connection, and find the address
* of the sender. */
newaddrsize = sizeof(newaddr);
psocks[plcount]=accept(mainsock,(struct sockaddr *)
&newaddr,&newaddrsize);
newhost = gethostbyaddr((char *)&newaddr.sin_addr.s_addr,
4,AF_INET);
hname = newhost ? newhost->h_name : "unknown";
/* tell player the version number */
nprintf(psocks[plcount],"%s\n",NET3D_VERSION);
/* get name from player, or version error */
pnames[plcount]=strdupe(ngets(psocks[plcount]));
if (!strcmp(pnames[plcount],VERSION_ERROR)) {
printf("player on machine %s has wrong version..."
"rejected\n",hname);
close(psocks[plcount]);
}
else {
printf("received connection from %s on %s\n",
pnames[plcount],hname);
plcount++;
}
}
} while(!FD_ISSET(0,&fds));
if (plcount)
printf("starting game with %d players\n",plcount);
else {
printf("no players :(\n");
exit(0);
}
/* list all players */
for(i=0; i<plcount; i++)
printf("Player %d is \"%s\"\n",i,pnames[i]);
/* once again, run all the vehicle files through cpp, but this time
* send them through the sockets to each client
*/
for(i=1; i<argc; i++) {
char syscom[100]; /* buffer used for 'popen' call */
FILE *pifp; /* file pointer for 'popen' call */
sprintf(syscom,"%s %s",CPPPATH,filepaths[i]);
pifp=popen(syscom,"r");
while(!feof(pifp)) {
char buf[100]; /* a line from the pre-processor */
int j;
/* read a line, and send it to all clients */
fgets(buf,100,pifp);
for(j=0; j<plcount; j++)
nprintf(psocks[j],"%s",buf);
}
pclose(pifp);
for(j=0; j<plcount; j++)
nprintf(psocks[j],"\n");
printf("done transmitting %s\n",filepaths[i]);
}
/* send the 'end' token to all clients, to indicate the end of
* the vehicle files
*/
for(i=0; i<plcount; i++)
nprintf(psocks[i],"\nend\n");
/* tell each client their player number */
vpos=vhead;
for(i=0; i<plcount; i++) {
if (vpos) {
printf("%s has vehicle %s\n",pnames[i],vpos->code);
nprintf(psocks[i],"%d\n",i);
vpos=vpos->next;
}
else {
printf("player %d has no vehicle!!\n",i);
break;
}
}
/* send 'no vehicle' signal to all clients who don't have a vehicle */
j=i;
for(; i<plcount; i++) {
nprintf(psocks[i],"-1\n",i);
shutdown(psocks[i],2);
close(psocks[i]);
}
/* truncate player list to the number who got vehicles */
plcount=j;
stillalive=plcount;
/* tell each client the number of players in the game, and the names
* of the players.
*/
for(i=0; i<plcount; i++) {
int j;
nprintf(psocks[i],"%d\n",plcount);
for(j=0; j<plcount; j++)
nprintf(psocks[i],"%s\n",pnames[j]);
}
/* store the vehicles owned by each player */
vpos=vhead;
for(i=0; i<plcount; i++) {
pvehicles[i]=vpos;
vpos=vpos->next;
}
/* send to each client a message consisting only of the game time,
* to start each client up.
*/
for(i=0; i<plcount; i++)
nprintf(psocks[i],"%lf\n",gametime());
/* The main server loop.
*
* In here, we wait for all the clients to reply with their commands,
* and once done, send gametime() and those commands to all clients.
*/
while(stillalive || finalcountdown) {
processnet(psocks,plcount,mainsock);
if (!stillalive)
finalcountdown--;
}
/* no-one is left. Send quit messages to all clients */
printf("All players destroyed. GAME OVER\n");
for(i=0; i<plcount; i++)
nprintf(psocks[i],"%lf q 0 0.0\n",gametime());
/* close all connections to players and the main socket
*/
for(i=0; i<plcount;i++) {
shutdown(psocks[i],2);
close(psocks[i]);
}
shutdown(mainsock,2);
close(mainsock);
return(0);
}
static void displayhelp(char *cn)
{
printf(
"net3d server help\n"
"-----------------\n"
"Server mode : To start the net3d server, type :\n"
" %s <vehicle file> <vehicle file> ...\n"
" Vehicle files have the extension .v, and at least one must\n"
" be given."
"\n"
" Once the server has started, it will wait for net3d clients\n"
" to connect, and display connections as they are received.\n"
" When enough connections have arrived, and you want to start\n"
" the game, hit return. Each player will be given a vehicle, and\n"
" the game will start\n"
,cn);
}